package com.clp.protocol.iec104.apdu.asdu.infoobj.infoelem;

import com.clp.protocol.iec104.apdu.asdu.infoobj.infoelem.filetransfer.AttachPack;
import com.clp.protocol.iec104.definition.Ft;
import com.clp.protocol.iec104.definition.TypeTag;
import com.clp.protocol.core.pdu.nbytepdu.BaseNBytePduClip;
import com.clp.protocol.core.pdu.ByteToStringFormat;
import io.netty.buffer.ByteBuf;
import lombok.Getter;

import java.util.Objects;
import java.util.function.Consumer;

/**
 * 文件传输 信息元素内容
 */
@Getter
public class F_FR_NA_2_InfoElem extends InfoElem {

    /**
     * 附加数据包类型
     */
    private Ft.AttachPackType attachPackType;

    /**
     * 附加数据包
     */
    private AttachPack attachPack;

    public F_FR_NA_2_InfoElem() {
        this(null, null);
    }

    public F_FR_NA_2_InfoElem(Ft.AttachPackType attachPackType, AttachPack attachPack) {
        super(TypeTag.F_FR_NA_2);
        this.attachPackType = attachPackType;
        this.attachPack = attachPack;
    }

    @Override
    public F_FR_NA_2_InfoElem refreshFrom(ByteBuf buf) {
        this.attachPackType = Ft.AttachPackType.gain(buf.readByte());
        this.attachPack = Ft.OperationTag.gain(buf.getByte(buf.readerIndex()) & 0xFF).newInvalidAttachPack();
        return this;
    }

    @Override
    public boolean isValid() {
        if (attachPackType == null) return false;
        return attachPack != null && attachPack.isValid();
    }

    @Override
    public void writeBytesTo(ByteBuf buf) {
        buf.writeByte(attachPackType.getVal());
        attachPack.writeBytesTo(buf);
    }

    @Override
    public void writeFormattedByteStringsTo(StringBuilder sb, String frameClipBytesSeparator, String byteSeparator, ByteToStringFormat byteFormat) {
        sb.append(byteFormat.format((byte) attachPackType.getVal()));
        sb.append(frameClipBytesSeparator);
        attachPack.writeFormattedByteStringsTo(sb, frameClipBytesSeparator, byteSeparator, byteFormat);
    }

    @Override
    public void writeSimpleDescriptionTo(StringBuilder sb) {
        sb.append(attachPackType);
        attachPack.writeSimpleDescriptionTo(sb);
    }

    @Override
    public void writeDetailDescriptionTo(StringBuilder sb) {
        sb.append("附加数据包类型：").append(attachPackType);
        sb.append(", 附加数据包："); attachPack.writeDetailDescriptionTo(sb);
    }

    @Override
    protected void forEachOneLevelChild(Consumer<BaseNBytePduClip<?>> consumer) {
        consumer.accept(attachPack);
    }

    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;
        F_FR_NA_2_InfoElem that = (F_FR_NA_2_InfoElem) o;
        return attachPackType == that.attachPackType && Objects.equals(attachPack, that.attachPack);
    }

    @Override
    public int hashCode() {
        return Objects.hash(attachPackType, attachPack);
    }
}
